/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


import java.awt.*;
import java.applet.*;
import java.awt.geom.*;
import java.awt.event.*;

import java.awt.image.*;
import java.util.*;





/**
 *
 * @author shohdi
 */
public class Astroids extends Applet implements Runnable , KeyListener  {
    BufferedImage bi = new  BufferedImage (640,480,BufferedImage.TYPE_4BYTE_ABGR);
    Graphics2D g2d = null ;
    boolean showBounds = false;
    Thread gameLoop = null;
    Ship ship = new  Ship();
    int astroidsCount = 20;
    int bulletsCount = 10;

    int currentBullet = 0;

    Astroid [] astroids = new Astroid[astroidsCount];
    Bullet[] bullets = new Bullet[bulletsCount];

    AffineTransform identity  = new  AffineTransform ();

    Random rand = new Random();


    public void init ()
    {
        g2d = bi.createGraphics();

        for (int n =0;n<bulletsCount;n++)
        {
            bullets[n] = new Bullet();
            bullets[n].setAlive(false);

        }


        for (int n=0;n<astroidsCount;n++)
        {
            astroids[n] = new Astroid();
            astroids[n].setAlive(true);
            astroids[n].setX (rand.nextInt(600) + 20);
            astroids[n].setY(rand.nextInt(440) + 20);

            astroids[n].setMoveAngle(rand.nextInt(360));
            double angle = astroids[n].getMoveAngle();
            astroids[n].setVelX (calcVelXByMoveAngle(angle));
            astroids[n].setVelY (calcVelYByMoveAngle(angle));
            astroids[n].setRotVel(rand.nextInt(3) + 1);




        }

        ship.setX(320);
        ship.setY(240);

        addKeyListener(this);

        gameLoop = new Thread(this);


    }

    public void keyReleased(KeyEvent e)
    {

    }

    public void keyPressed(KeyEvent e)
    {
        switch (e.getKeyCode())
        {
            case KeyEvent.VK_RIGHT:
                ship.incFaceAngle(5);
                if (ship.getFaceAngle() > 360)
                    ship.setFaceAngle((ship.getFaceAngle())-360);
                break;

            case KeyEvent.VK_LEFT:
                ship.incFaceAngle(-5);
                if (ship.getFaceAngle() < 0)
                    ship.setFaceAngle((ship.getFaceAngle()) + 360);
                break;

            case KeyEvent.VK_UP :
                ship.setMoveAngle (ship.getFaceAngle()-90);
                if (ship.getMoveAngle() < 0)
                {
                    ship.setMoveAngle(360 + ship.getMoveAngle());

                }
                ship.setVelX(ship.getVelX() + (calcVelXByMoveAngle(ship.getMoveAngle()) * 0.1));
                ship.setVelY(ship.getVelY() + (calcVelYByMoveAngle(ship.getMoveAngle()) * 0.1));
                break;

            case (KeyEvent.VK_B):
                showBounds= !showBounds;
                break;


            case KeyEvent.VK_ENTER:
            case KeyEvent.VK_SPACE:
            case KeyEvent.VK_CONTROL:
                currentBullet++;
                if (currentBullet >= bulletsCount)
                {
                    currentBullet = 0;


                }

                bullets[currentBullet].setAlive(true);
                bullets[currentBullet].setX(ship.getX());
                bullets[currentBullet].setY(ship.getY());
                bullets[currentBullet].setMoveAngle(ship.getFaceAngle()-90);
                bullets[currentBullet].setVelX(ship.getVelX() + (calcVelXByMoveAngle(bullets[currentBullet].getMoveAngle()) * 2));
                bullets[currentBullet].setVelY(ship.getVelY() + (calcVelYByMoveAngle(bullets[currentBullet].getMoveAngle()) * 2));

                break;



        }
    }

    public void keyTyped(KeyEvent e)
    {

    }


    public void update(Graphics g)
    {

        g2d.setTransform(identity);
        g2d.setColor(Color.BLACK);
        g2d.fill(new Rectangle(0,0,getSize().width,getSize().height));
        g2d.setColor(Color.WHITE);
        g2d.setFont(new Font("Tahoma",Font.PLAIN,12));

        g2d.drawString("ship : " + Math.round(ship.getX()) + " , " + Math.round(ship.getY()),5,10);
        g2d.drawString("Face angle : " + Math.round((ship.getFaceAngle())), 5,25);
        g2d.drawString("Move Angle : " + Math.round((ship.getMoveAngle() + 90)%360),5, 45);

        drawShip();
        drawBullets();
        drawAstroids();





        paint(g);
    }


    private void drawShip()
    {
        g2d.setTransform(identity);
        g2d.translate(ship.getX(),ship.getY());
        g2d.rotate(Math.toRadians(ship.getFaceAngle()));
        g2d.setColor(Color.ORANGE);
        g2d.fill(ship.getShape());

        if (showBounds)
        {
            g2d.setTransform(identity);

            g2d.setColor(Color.WHITE);

            g2d.draw(ship.getBounds());
        }

    }


    private void drawBullets()
    {
        for (int n=0;n<bulletsCount;n++)
        {
            if (bullets[n].isAlive())
            {
                g2d.setTransform(identity);
                g2d.translate(bullets[n].getX(),bullets[n].getY());

                g2d.setColor(Color.MAGENTA);
                g2d.fill(bullets[n].getShape());
            }
        }
    }


    private void drawAstroids()
    {
        for (int n=0;n<astroidsCount;n++)
        {
            if (astroids[n].isAlive())
            {
                g2d.setTransform(identity);
                g2d.translate(astroids[n].getX(),astroids[n].getY());
                g2d.rotate(Math.toRadians((astroids[n].getMoveAngle())));
                g2d.setColor(Color.GRAY);
                g2d.fill(astroids[n].getShape());

                if (showBounds)
                {
                    g2d.setTransform(identity);

                    g2d.setColor(Color.WHITE);

                    g2d.draw(astroids[n].getBounds());
                }
            }
        }
    }

    public void start ()
    {

        gameLoop.start();
    }

    public void stop ()
    {
        gameLoop = null;

    }


    public void run( )
    {
        Thread t = Thread.currentThread();

        while (t == gameLoop)
        {
            try
            {
                gameUpdate();

                Thread.sleep(20);
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }




        }
    }

    private void gameUpdate()
    {
        updateShip ();
        updateBullets();
        updateAstroids();

        checkForCollision();

        this.update(this.getGraphics());

    }


    private void updateShip()
    {
        ship.incX(ship.getVelX());
        if (ship.getX() > 640)
        {
            ship.setX(0);
        }
        else if (ship.getX() < 0)
        {
            ship.setX(640);
        }

        ship.incY(ship.getVelY());

        if (ship.getY() > 480)
        {
            ship.setY(0);
        }
        else if (ship.getY()< 0)
        {
            ship.setY(480);
        }


    }


    private void updateBullets()
    {
        for (int n=0;n<bulletsCount;n++)
        {
            if (bullets[n].isAlive())
            {
                bullets[n].incX(bullets[n].getVelX());
                if (bullets[n].getX() > 640 || bullets[n].getX()< 0)
                    bullets[n].setAlive(false);
                bullets[n].incY(bullets[n].getVelY());
                if (bullets[n].getY() > 480 || bullets[n].getY() < 0)
                    bullets[n].setAlive(false);

            }


        }
    }


    private void updateAstroids()
    {
        for (int n=0;n<astroidsCount;n++)
        {
            if (astroids[n].isAlive())
            {
                astroids[n].incX(astroids[n].getVelX());
                if (astroids[n].getX() > 640)
                {
                    astroids[n].setX(0);
                }
                else if (astroids[n].getX() < 0)
                {
                    astroids[n].setX(640);
                }


                astroids[n].incY(astroids[n].getVelY());
                if (astroids[n].getY() > 480)
                {
                    astroids[n].setY(0);
                }
                else if (astroids[n].getY() < 0)
                {
                    astroids[n].setY(480);
                }


                astroids[n].incMoveAngle(astroids[n].getRotVel());
                if (astroids[n].getMoveAngle()> 360)
                    astroids[n].setMoveAngle(astroids[n].getMoveAngle()-360);
                else if (astroids[n].getMoveAngle() < 0)
                    astroids[n].setMoveAngle(astroids[n].getMoveAngle() + 360);


            }
        }
    }


    private void checkForCollision()
    {
        for (int n=0;n<astroidsCount;n++)
        {
            if (astroids[n].isAlive())
            {
                for (int m=0;m<bulletsCount;m++)
                {
                     if (bullets[m].isAlive())
                     {
                         if (astroids[n].getBounds().contains(bullets[m].getBounds()))
                         {
                             bullets[m].setAlive(false);
                             astroids[n].setAlive(false);
                         }
                     }
                }

                if (astroids[n].getBounds().intersects(ship.getBounds()))
                {
                    ship.setX(320);
                    ship.setY(240);
                    ship.setMoveAngle(0);
                    ship.setFaceAngle(0);
                    ship.setVelX(0);
                    ship.setVelY(0);



                    astroids[n].setAlive(false);

                }

            }
        }
    }









    public void paint(Graphics g)
    {

        g.drawImage(bi, 0, 0, this);
    }

    private double calcVelXByMoveAngle(double angle)
    {
        return Math.cos(angle * Math.PI/180);


    }

    private double calcVelYByMoveAngle(double angle)
    {
        return Math.sin(angle * Math.PI/180);

    }



    public static void main(String [] args)
    {}


}